package com.oig.sys.base.service.impl;

import cn.hutool.core.util.StrUtil;
import com.oig.common.constants.CommonEnum;
import com.oig.common.exception.BadRequestException;
import com.oig.common.module.SysPageInfo;
import com.oig.common.module.SysRequest;
import com.oig.sys.base.dao.ITbHsGoodsDao;
import com.oig.sys.base.dto.HsGoodsDto;
import com.oig.sys.base.entity.TbHsGoods;
import com.oig.sys.base.service.ITbHsGoodsService;
import com.oig.sys.base.vo.HsGoodsVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author wuxl
 */
@Service
public class TbHsGoodsServiceImpl implements ITbHsGoodsService {

	private final ITbHsGoodsDao tbHsGoodsDao;

	@Autowired
	public TbHsGoodsServiceImpl(ITbHsGoodsDao tbHsGoodsDao){
		 this.tbHsGoodsDao = tbHsGoodsDao;
	}

	@Transactional
	@Override
	public HsGoodsVo addHsGoods(HsGoodsDto hsGoodsDto) {
		TbHsGoods hsGoods = new TbHsGoods();
		BeanUtils.copyProperties(hsGoodsDto, hsGoods);
		hsGoods.setUpdateTime(new Date());
		hsGoods.setStatus(CommonEnum.CommonStatusEnum.OK.getCode());
		this.tbHsGoodsDao.save(hsGoods) ;
		return buildVo(hsGoods);
	}

	private HsGoodsVo buildVo(TbHsGoods hsGoods){
		HsGoodsVo hsGoodsVo = new HsGoodsVo();
		BeanUtils.copyProperties(hsGoods, hsGoodsVo);
		return hsGoodsVo;
	}

	@Transactional
	@Override
	public HsGoodsVo updateHsGoods(HsGoodsDto hsGoodsDto) {
		TbHsGoods hsGoods = this.tbHsGoodsDao.getByHsCode(hsGoodsDto.getHsCode()) ;
		if (hsGoods==null) {
			throw new BadRequestException("无hsCode="+hsGoodsDto.getHsCode()+"海关商品记录") ;
		}
		BeanUtils.copyProperties(hsGoodsDto,hsGoods,"hsCode","status");
		hsGoods.setUpdateTime(new Date());
		this.tbHsGoodsDao.save(hsGoods);
		return buildVo(hsGoods);
	}

	@Transactional
	@Override
	public HsGoodsVo updateHsGoodsTax(HsGoodsDto hsGoodsDto) {
		TbHsGoods hsGoods = this.tbHsGoodsDao.getByHsCode(hsGoodsDto.getHsCode()) ;
		if (hsGoods==null) {
			return null; 	//不报错直接返回
		}
		hsGoods.setName(hsGoodsDto.getName());
		hsGoods.setTariffType(hsGoodsDto.getTariffType());
		hsGoods.setOffTariffRate(hsGoodsDto.getOffTariffRate());	//最惠
		hsGoods.setProvTaxRate(hsGoodsDto.getProvTaxRate());	//暂定
		hsGoods.setCommTariffRate(hsGoodsDto.getCommTariffRate());//普通
		hsGoods.setCmpTaxRate(hsGoodsDto.getCmpTaxRate());//消费税税率
		hsGoods.setVatRate(hsGoodsDto.getVatRate());//增值
		hsGoods.setRemark("海关网站获取税率");
		hsGoods.setUpdateTime(new Date());
		this.tbHsGoodsDao.save(hsGoods);
		return buildVo(hsGoods);
	}

	@Transactional
	@Override
	public void updateSpiderHsGoods(HsGoodsDto hsGoodsDto) {
		TbHsGoods hsGoods = this.tbHsGoodsDao.getByHsCode(hsGoodsDto.getHsCode()) ;
		if (hsGoods==null) {
			throw new BadRequestException("无hsCode="+hsGoodsDto.getHsCode()+"海关商品记录") ;
		}
		if (!"正常".equals(hsGoodsDto.getStatus())|| StringUtils.isBlank(hsGoodsDto.getName())){
			hsGoods.setStatus(CommonEnum.CommonStatusEnum.DEL.getCode());
			hsGoods.setUpdateTime(new Date());
			this.tbHsGoodsDao.save(hsGoods);
			return;
		}
		hsGoods.setName(hsGoodsDto.getName());
		hsGoods.setUnit1(hsGoodsDto.getUnit1());
		hsGoods.setTariffType(hsGoodsDto.getTariffType());
		hsGoods.setOffTariffRate(hsGoodsDto.getOffTariffRate());	//最惠
		hsGoods.setProvTaxRate(hsGoodsDto.getProvTaxRate());	//3 暂定
		hsGoods.setCommTariffRate(hsGoodsDto.getCommTariffRate()); //普通
		hsGoods.setCmpTaxRate(hsGoodsDto.getCmpTaxRate());	//消费税税率
		hsGoods.setVatRate(hsGoodsDto.getVatRate());	//增值
		hsGoods.setRebateRate(hsGoodsDto.getRebateRate());	//出口退税
		hsGoods.setExportProvTaxRate(hsGoodsDto.getExportProvTaxRate());	//4出口暂定
		hsGoods.setExportRate(hsGoodsDto.getExportRate());	//出口
		hsGoods.setGwUpdateDate(hsGoodsDto.getGwUpdateDate());//1
		hsGoods.setMonitor(hsGoodsDto.getMonitor());
		hsGoods.setIqType(hsGoodsDto.getIqType());
		hsGoods.setRemark(hsGoodsDto.getRemark());	//2
		hsGoods.setUpdateTime(new Date());
		this.tbHsGoodsDao.save(hsGoods) ;
	}

	@Transactional
	@Override
	public HsGoodsVo cancelHsGoods(String hsCode) {
		TbHsGoods hsGoods = this.tbHsGoodsDao.getByHsCode(hsCode) ;
		if (hsGoods==null) {
			throw new BadRequestException("无hsCode="+hsCode+"海关商品记录") ;
		}
		hsGoods.setStatus(CommonEnum.CommonStatusEnum.DEL.getCode());
		this.tbHsGoodsDao.save(hsGoods) ;
		return this.buildVo(hsGoods);
	}


	@Override
	public HsGoodsVo getHsGoods(String hsCode) {
		TbHsGoods hsGoods = this.tbHsGoodsDao.getByHsCode(hsCode) ;
		if (hsGoods==null) {
			throw new BadRequestException("无hsCode="+hsCode+"海关商品记录") ;
		}
		return this.buildVo(hsGoods);
	}

	@Override
	public SysPageInfo<HsGoodsVo> listHsGoods(SysRequest<HsGoodsDto> hsGoodsRequest) {
		Pageable pageable = hsGoodsRequest.pageable();
		Page<TbHsGoods> page ;
		if (hsGoodsRequest.getParamDto()!=null){
			Specification<TbHsGoods> specification = new Specification<TbHsGoods>() {
				@Override
				@Nullable
				public Predicate toPredicate(@NonNull Root<TbHsGoods> root, @NonNull CriteriaQuery<?> criteriaQuery, @NonNull CriteriaBuilder criteriaBuilder) {
					List<Predicate> predicateList = new ArrayList<>();
					if (hsGoodsRequest.getParamDto().getHsCode()!=null) {
						Path<String> hsCodePath = root.get("hsCode");
						predicateList.add(criteriaBuilder.equal(hsCodePath,  hsGoodsRequest.getParamDto().getHsCode() ));
					}
					if (StrUtil.isNotBlank(hsGoodsRequest.getParamDto().getName())) {
						Path<String> namePath = root.get("name");
						predicateList.add(criteriaBuilder.like(namePath, "%" + hsGoodsRequest.getParamDto().getName()+ "%"));
					}
					if (StrUtil.isNotBlank(hsGoodsRequest.getParamDto().getTariffType())) {
						Path<String> TrfPath = root.get("tariffType");
						predicateList.add(criteriaBuilder.equal(TrfPath, hsGoodsRequest.getParamDto().getTariffType()));
					}
					if (StrUtil.isNotBlank(hsGoodsRequest.getParamDto().getStatus())){
						Path<String> statusPath = root.get("status");
						predicateList.add(criteriaBuilder.equal(statusPath, hsGoodsRequest.getParamDto().getStatus()));
					}

					if (StrUtil.isNotBlank(hsGoodsRequest.getParamDto().getSearchWord())){
						Path<String> name = root.get("name");
						Path<String> hsCode = root.get("hsCode");
						String searchWord = "%" + hsGoodsRequest.getParamDto().getSearchWord() + "%";
						Predicate or = criteriaBuilder.or(criteriaBuilder.like(name, searchWord), criteriaBuilder.like(hsCode, searchWord));
						predicateList.add(or);
					}

					criteriaQuery.where(predicateList.toArray(new Predicate[0]));
					return criteriaQuery.getRestriction();
				}
			};
			page = this.tbHsGoodsDao.findAll(specification,pageable);
		} else {
			page = this.tbHsGoodsDao.findAll(pageable);
		}
		List<HsGoodsVo> hsGoodsVoList = new ArrayList<>();
		for (TbHsGoods hsGoods : page.getContent()){
			hsGoodsVoList.add(buildVo(hsGoods));
		}
		SysPageInfo<HsGoodsVo> sysPageInfo = new SysPageInfo<>(hsGoodsRequest.getPageNo(), hsGoodsRequest.getPageSize(), page.getTotalElements());
		sysPageInfo.setList(hsGoodsVoList);
		return sysPageInfo;
	}

	@Override
	public String getName(String hsCode) {
		return this.tbHsGoodsDao.getNameByHsCode(hsCode);
	}


	@Override
	public List<HsGoodsVo> listInfoByHsCode(List<String> hsCode) {
		return this.tbHsGoodsDao.findAllByHsCodeIn(hsCode).stream().map(this::buildVo).collect(Collectors.toList());
	}
}
